# @Time    : 2017/11/6 下午2:12
# @Author  : JCD
# @File    : do_task.py
from multiprocessing import Pool
import os
import sys
from xml.etree import ElementTree

__path_temp = None


def do_pool():
    """
    通过进程池执行任务
    进程池默认大小为10,可通过修改配置文件改变
    :return:
    """
    # 设置默认进程池大小为10
    pool_size = 10

    # 获取配置文件路径
    for path in sys.path:
        __find_file(path, 'config.xml')
        if not (__path_temp is None):
            break
    if __path_temp is None:
        raise FileNotFoundError('No such *config.xml!')

    # 读取配置文件
    root = __read_xml(__path_temp)

    # 读取配置文件中进程池大小
    pool_size_config = root.find('./options/pool_size')
    # 如果配置文件内进程池不为空则以配置文件中值为准
    if not (pool_size_config is None):
        pool_size = int(pool_size_config.text)

    # 读取要执行的任务
    tasks = root.find('./tasks')
    if tasks is None:
        raise ValueError('No Task!')
    # 开启进程池
    pool = Pool(pool_size)
    # 遍历任务
    for task in tasks:
        # 是否执行任务
        flag = True
        if task is None:
            raise ValueError('No Task!')

        task_class = task.find('task_class')
        task_package = task.find('task_package')

        if task_class is None:
            print('task_class is None!')
            flag = False
        if task_package is None:
            print('task_package is None!')
            flag = False

        if flag:
            # 执行任务
            pool.apply_async(func=__execute, args=(task_class.text, task_package.text,))

    pool.close()
    pool.join()


def do_dict(task_list, pool_size=10):
    """
    以单进程方式依次执行字典中的任务
    :param task_list: 执行任务列表,key: 执行类名, value: 执行类所在包名
    :param pool_size: 进程池大小,默认为10
    :return:
    """
    if task_list is None:
        raise ValueError('task_list can`t be None!')
    if not isinstance(task_list, dict):
        raise ValueError('task_list must be dict!')

    pool = Pool(pool_size)

    for class_name, package_name in task_list.items():
        # 执行任务
        pool.apply_async(func=__execute, args=(class_name, package_name,))

    pool.close()
    pool.join()


def do(class_name, package_name):
    """
    单进程执行单一任务
    :param class_name: 执行类名
    :param package_name: 执行类所在包名
    :return:
    """
    if (class_name is None or '' == class_name) or (package_name is None or '' == package_name):
        raise ValueError('class_name or package_name can`t be None!')
    __execute(class_name, package_name)


def __execute(class_name, package_name):
    execute_module = __import__(package_name, fromlist=True)
    execute = getattr(execute_module, class_name)
    execute().do_task()


def __find_file(d, file):
    global __path_temp
    try:
        for f in os.listdir(d):
            f = os.path.join(d, f)
            if os.path.isfile(f):
                if file in os.path.split(f)[1]:
                    __path_temp = os.path.abspath(f)
                    break
            else:
                __find_file(f, file)
    except Exception:
        pass


def __read_xml(file):
    root = ElementTree.parse(file)
    return root